#include "pref.h"
#include <map>
#include <QDebug>

using namespace std;

#include "pkeylist.h"

#include "QtDebug.h"

string PRef::m_objname = "PRef";

PRef::PRef()
{
}

PRef::PRef(const PKeyList* plist)
{
    m_appendRefFrom(plist);
}

PRef::PRef(const PRef& ref) :
    m_ref_vector( ref.m_ref_vector )
{
}

PRef& PRef::operator = (const PRef& ref)
{
    m_ref_vector = ref.m_ref_vector;
    return *this;
}

const PKeyItem& PRef::getRefFrom( const int& iref, int& err ) const
{
    unsigned int nb = m_count(iref);
    if ( nb == 1 )
    {
        err = PRef::ERR_NONE;
        PKeyItem k = m_ref_vector.at(m_findPos(iref).front());
        return k;
    }
    else if ( nb > 1)
    {
        err = PRef::ERR_KEY_NOT_UNIQUE;
        PKeyItem k;
        return k;
    }
    else
    {
        err = PRef::ERR_GENERIC;
        PKeyItem k;
        return k;
    }
}

void PRef::setRefFrom( const PKeyItem& ref_from, int& err )
{
    int nb = m_count(ref_from.getTabRef());
    if ( nb == 1 )
    {
        err = PRef::ERR_NONE;
        m_ref_vector[m_findPos(ref_from.getTabRef()).front()] = ref_from;
    }
    else if ( nb > 1 )
    {
        err = PRef::ERR_KEY_NOT_UNIQUE;
    }
    else
    {
        err = PRef::ERR_GENERIC;
    }
}


const PKeyItem& PRef::getRefFrom( const int& iref ) const
{
    int err;
    return getRefFrom(iref,err);
}


void PRef::setRefFrom( const PKeyItem& ref_from)
{
    int err;
    setRefFrom(ref_from,err);
}

void PRef::m_appendRefFrom(const PKeyList* plist)
{
    list<PKeyItem> keyl;
    plist->createRef(keyl);
    list<PKeyItem>::iterator it;
    for (it = keyl.begin(); it != keyl.end(); ++it)
    {
        m_ref_vector.push_back(*it);
    }
}

void PRef::m_appendRefFrom( const PKeyItem &key )
{
    // qDebug()<<"PRef::m_appendRefFrom( const PKey &key )";
    m_ref_vector.push_back(key);
}

int PRef::nbRefFrom( void ) const
{
    int size = m_ref_vector.size();
    return (size);
}

int PRef::nbRefFrom( const PKeyItem& ref_from ) const
{
    unsigned int nb = 0;
    for (unsigned int i=0; i < m_ref_vector.size(); i++)
    {
        PKeyItem k = m_ref_vector.at(i);
        if ( k.getTabRef() == ref_from.getTabRef()
                           &&
             k.getKeyStr() == ref_from.getKeyStr() )
        {
            nb = nb + 1;
        }
    }
    return nb;
}

PKeyItem& PRef::operator[]( unsigned int i )
{
    if ( i>=0 && i<m_ref_vector.size())
    {
        return m_ref_vector[i];
    }
    else
    {
        unsigned int nb = i-m_ref_vector.size()+1;
        m_ref_vector.resize(nb+m_ref_vector.size());
        return m_ref_vector[i];
    }
}

void PRef::delRefFrom( const ExaTabRef& ref )
{
    setRefFrom(PKeyItem(ref));
}

void PRef::delRefFrom( const ExaTabRef& ref, int& err)
{
    setRefFrom(PKeyItem(ref),err);
}

unsigned int PRef::m_count( const int& ref_tab ) const
{
    unsigned int nb = 0;
    for (unsigned int i=0; i < m_ref_vector.size(); i++)
    {
        PKeyItem k = m_ref_vector.at(i);
        if ( k.getTabRef() == ref_tab )
        {
            nb = nb + 1;
        }
    }
    return nb;
}

list <unsigned int> PRef::m_findPos( const int& ref_tab ) const
{
    list <unsigned int> pos_list;
    for (unsigned int i=0; i < m_ref_vector.size(); i++)
    {
        PKeyItem k = m_ref_vector.at(i);
        if ( k.getTabRef() == ref_tab )
        {
            pos_list.push_back(i);
        }
    }
    return pos_list;
}

void PRef::reportMake(const string& objname) const
{
    if (getReportCurrentStyle() == STYLE_VERBOSE)
    {
        addInLine("n.ref",nbRefFrom());
        moveLineInBlock();
        for (unsigned int i=0; i < m_ref_vector.size(); i++)
        {
            PKeyItem k = m_ref_vector.at(i);
            addInLine("i",int(i));
            addInLine("key",k.getKeyStr());
            addInLine("descr",k.getDescr());
            addInLine("tab_ref",k.getTabRef());
            addInLine("tab_name",PKeyList::getListNameFromId(k.getTabRef()),0);
            moveLineInBlock();
        }
    }
    else if (getReportCurrentStyle() == STYLE_COMPACT)
    {
        for (unsigned int i=0; i < m_ref_vector.size(); i++)
        {
            PKeyItem k = m_ref_vector.at(i);
            addInLine("key",k.getKeyStr(),2);
            addInLine("tab_ref",k.getTabRef(),2);
        }
        moveLineInBlock();
    }
    PReport::reportMake(m_objname);
}

void PRef::appendRefFrom (const vector<PKeyItem> &vec)
{
    unsigned int nb = 0;
    for (unsigned int i=0; i < vec.size(); i++)
    {
        m_ref_vector.push_back(vec[i]);
    }
}

bool PRef::hasRefFrom( const PKeyItem &key_item ) const
{
    for (unsigned int i=0; i < m_ref_vector.size(); i++)
    {
        PKeyItem k = m_ref_vector.at(i);
        if ((k.getKeyStr() == key_item.getKeyStr()) &&
            (k.getTabRef() == key_item.getTabRef())
           )
        {
            return true;
        }
    }
    return false;
}





